package com.example.demo.handler;

import cn.hutool.json.JSONUtil;
import com.example.demo.entity.ChatMessage;
import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import com.example.demo.service.IMessageService;
import com.example.demo.service.UserStatusService;
import com.example.demo.utils.SpringContext;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static com.example.demo.utils.Constants.MESSAGE_TYPE_PUBLIC;

@Component
public class ChatWebSocketHandler extends TextWebSocketHandler {

    //存储所有的session会话
    Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>();

    // 连接建立时触发
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        UserStatusService statusService = SpringContext.getBean(UserStatusService.class);
        UserMapper userMapper = SpringContext.getBean(UserMapper.class);
        Integer userId = extractUserIdFromSession(session);
        System.out.println("-----------------------用户：" + userId + "连接成功！---------------");
        String key = null;
        if(session.getAttributes().get("receiveUsername") != null){
            String receiveUsername = (String) session.getAttributes().get("receiveUsername");
            Integer receiveId = userMapper.getUserByUsername(receiveUsername).getUserId();
            System.out.println("-----------------------被私聊用户：" + receiveUsername
                    + "在线状态： " + statusService.isUserOnline(receiveId));
            key = userId + "-" + receiveId;
        }else {
            key = "public-" + userId;
        }
        sessions.put(key, session);
        statusService.isUserOnline(userId);
    }

    // 收到消息时触发
    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        String username = (String) session.getAttributes().get("username");
        ChatMessage chatMessage = parseMessage((String) message.getPayload());
        if (chatMessage.getKey() != null){
            System.out.println("session = " + session);
            return;
        }
        chatMessage.setSenderUsername(username);
        if (chatMessage.getType().equals(MESSAGE_TYPE_PUBLIC)){
            SpringContext.getBean(IMessageService.class).savePublicMessage(chatMessage);
            sessions.forEach((key, webSocketSession) -> {
                if (key.startsWith("public")){
                    chatMessage.filter();
                    try {
                        webSocketSession.sendMessage(new TextMessage(JSONUtil.toJsonPrettyStr(chatMessage)));
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
            });
        }else {
            String receiveUsername = (String) session.getAttributes().get("receiveUsername");
            chatMessage.setReceiveUsername(receiveUsername);
            User senderUser = SpringContext.getBean(UserMapper.class).getUserByUsername(chatMessage.getSenderUsername());
            User receiveUser = SpringContext.getBean(UserMapper.class).getUserByUsername(chatMessage.getReceiveUsername());
            // 保存信息(因为就算sessions里面有receiver的session，也不一定是跟当前用户连接的，所以直接保存）
            Integer messageId = SpringContext.getBean(IMessageService.class).savePrivateMessage(chatMessage);
            chatMessage.filter();
            // 如果要跟对方实时聊天的话，需要按照receiveUserId-senderId去查找session
            WebSocketSession chatSession = sessions.get(senderUser.getUserId() + "-" + receiveUser.getUserId());
            // 如果对方也开启了跟当前用户的ws的话，就发送给对方，并设置消息为已读
            try{
                WebSocketSession receiveSession = sessions.get(receiveUser.getUserId() + "-" + senderUser.getUserId());
                receiveSession.sendMessage(new TextMessage(JSONUtil.toJsonPrettyStr(chatMessage)));
                SpringContext.getBean(IMessageService.class).markMessageAsRead(Long.valueOf(messageId));
            }catch (Exception e){
                System.out.println("-----------------------被私聊用户:" + receiveUsername + "未开启对应session");
            }
            chatSession.sendMessage(new TextMessage(JSONUtil.toJsonPrettyStr(chatMessage)));
        }
    }

    // 连接关闭时触发
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        Integer userId;
        Integer receiveUserId;
        String key = "";
        try{
            userId = (Integer) session.getAttributes().get("userId");
            receiveUserId = (Integer) session.getAttributes().get("receiveUserId");
            if (receiveUserId != null){
                key = userId + "-" + receiveUserId;
            }else {
                key = "public-" + userId;
            }
            sessions.remove(key);
            System.out.println("-----------------------用户：" + userId +"已登出");
        }catch (Exception e){
            System.out.println("userId或receiveUserId为null，具体报错：" + e);
        }
    }


    private static Integer extractUserIdFromSession(WebSocketSession session) {
        return (Integer) session.getAttributes().get("userId");
    }

    // 解析消息内容（JSON -> ChatMessage）
    private ChatMessage parseMessage(String payload) {
        return JSONUtil.toBean(payload, ChatMessage.class);
    }

}
